package com.example.teemor.es_demo.service;

import com.example.teemor.es_demo.entity.ProductMySQL;
import com.example.teemor.es_demo.entity.ProductES;
import com.example.teemor.es_demo.repository.jpa.ProductMySQLRepository;
import com.example.teemor.es_demo.repository.es.ProductESRepository;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.ArrayList;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ProductService {
    
    private final ProductMySQLRepository productMySQLRepository;
    private final ProductESRepository productESRepository;

    /**
     * 保存商品（同时保存到MySQL和Elasticsearch）
     */
    @Transactional
    public ProductMySQL save(ProductMySQL product) {
        log.info("Saving product: {}", product.getTitle());
        
        // 保存到MySQL
        ProductMySQL saved = productMySQLRepository.save(product);
        
        try {
            // 同步到Elasticsearch
            productESRepository.save(new ProductES(saved));
            log.info("Product synced to Elasticsearch: {}", saved.getId());
        } catch (Exception e) {
            log.error("Failed to sync product to Elasticsearch", e);
            // 这里可以选择是否回滚MySQL事务，或者使用异步重试机制
        }
        
        return saved;
    }

    @Transactional
    public ProductMySQL update(Long id, ProductMySQL productDetails) {
        ProductMySQL existingProduct = productMySQLRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("商品不存在"));
        
        existingProduct.setTitle(productDetails.getTitle());
        existingProduct.setDescription(productDetails.getDescription());
        existingProduct.setPrice(productDetails.getPrice());
        existingProduct.setStock(productDetails.getStock());
        existingProduct.setCategory(productDetails.getCategory());
        existingProduct.setBrand(productDetails.getBrand());
        existingProduct.setImages(productDetails.getImages());
        
        return save(existingProduct);
    }

    /**
     * 获取所有商品（MySQL）
     */
    public Page<ProductMySQL> findAll(Pageable pageable) {
        return productMySQLRepository.findAll(pageable);
    }

    public List<ProductMySQL> findAllMySQL() {
        Iterable<ProductMySQL> productsIterable = productMySQLRepository.findAll();
        List<ProductMySQL> products = new ArrayList<>();
        productsIterable.forEach(products::add);
        return products;
    }

    /**
     * 根据ID查找商品（MySQL）
     */
    public Optional<ProductMySQL> findByIdMySQL(Long id) {
        return productMySQLRepository.findById(id);
    }

    /**
     * 删除商品
     */
    @Transactional
    public void deleteById(Long id) {
        log.info("Deleting product: {}", id);
        
        // 从MySQL删除
        productMySQLRepository.deleteById(id);
        
        try {
            // 从Elasticsearch删除
            productESRepository.deleteById(id);
            log.info("Product deleted from Elasticsearch: {}", id);
        } catch (Exception e) {
            log.error("Failed to delete product from Elasticsearch", e);
        }
    }

    /**
     * 搜索商品（Elasticsearch）
     */
    public Iterable<ProductES> searchES(String keyword) {
        log.info("Searching products with keyword: {}", keyword);
        
        // 使用ElasticsearchRepository的方法进行模糊搜索
        return productESRepository.findByTitleContainingOrDescriptionContainingOrBrandContainingOrCategoryContainingOrTagsContaining(
            keyword, keyword, keyword, keyword, keyword
        );
    }

    public Page<ProductES> findAllES(Pageable pageable) {
        return productESRepository.findAll(pageable);
    }

    public List<ProductES> findByCategoryES(String category) {
        return productESRepository.findByCategoryContaining(category);
    }

    public List<ProductES> findByBrandES(String brand) {
        return productESRepository.findByBrandContaining(brand);
    }

    /**
     * 根据分类查找商品
     */
    public List<ProductMySQL> findByCategory(String category) {
        return productMySQLRepository.findByCategory(category);
    }

    /**
     * 根据品牌查找商品
     */
    public List<ProductMySQL> findByBrand(String brand) {
        return productMySQLRepository.findByBrand(brand);
    }

    /**
     * 根据价格范围查找商品
     */
    public List<ProductMySQL> findByPriceRange(Double minPrice, Double maxPrice) {
        return productMySQLRepository.findByPriceBetween(minPrice, maxPrice);
    }

    /**
     * 查找有库存的商品
     */
    public List<ProductMySQL> findInStock() {
        return productMySQLRepository.findByStockGreaterThan(0);
    }

    /**
     * 获取商品总数
     */
    public long getProductCount() {
        return productMySQLRepository.count();
    }

    /**
     * 获取所有分类
     */
    public List<String> getAllCategories() {
        return productMySQLRepository.findDistinctCategories();
    }

    /**
     * 获取所有品牌
     */
    public List<String> getAllBrands() {
        return productMySQLRepository.findDistinctBrands();
    }

    /**
     * 根据分类统计商品数量
     */
    public List<Object[]> countByCategory() {
        return productMySQLRepository.countByCategory();
    }

    /**
     * 根据品牌统计商品数量
     */
    public List<Object[]> countByBrand() {
        return productMySQLRepository.countByBrand();
    }

    /**
     * 获取热门商品（根据某种规则，这里简单按ID倒序）
     */
    public List<ProductMySQL> getPopularProducts(int limit) {
        List<ProductMySQL> allProducts = findAllMySQL();
        return allProducts.stream()
                .sorted((p1, p2) -> p2.getId().compareTo(p1.getId()))
                .limit(limit)
                .collect(Collectors.toList());
    }

    /**
     * 搜索商品（支持分类过滤）
     */
    public Iterable<ProductES> searchESWithCategory(String keyword, String category) {
        if (category != null && !category.isEmpty()) {
            return productESRepository.findByTitleContainingAndCategoryContaining(keyword, category);
        }
        return searchES(keyword);
    }

    /**
     * 批量更新商品库存
     */
    @Transactional
    public void updateStock(Long productId, int quantity) {
        log.info("Updating stock for product: {}, quantity: {}", productId, quantity);
        
        ProductMySQL product = productMySQLRepository.findById(productId)
                .orElseThrow(() -> new RuntimeException("商品不存在: " + productId));
        
        int newStock = product.getStock() + quantity;
        if (newStock < 0) {
            throw new RuntimeException("库存不足");
        }
        
        product.setStock(newStock);
        save(product); // 这会同时更新MySQL和Elasticsearch
    }

    /**
     * 同步所有商品到Elasticsearch
     */
    @Transactional(readOnly = true)
    public void syncAllToElasticsearch() {
        log.info("Starting sync all products to Elasticsearch");
        
        List<ProductMySQL> allProducts = findAllMySQL();
        for (ProductMySQL product : allProducts) {
            try {
                productESRepository.save(new ProductES(product));
            } catch (Exception e) {
                log.error("Failed to sync product {} to Elasticsearch", product.getId(), e);
            }
        }
        
        log.info("Completed sync {} products to Elasticsearch", allProducts.size());
    }
}